Linux: O graceful shutdown

OpenCPN and Linux powerup/down management

Problem

I've been struggling to find a solution to the problem where OpenCPN shuts down 'violently' as e.g. can be seen in bug report FS#2245.

In Linux this is not an OpenCPN problem but is related to systemd so I found a workaround that ia published here.

Starting and stopping OpenCPN on a dedicated system with Ubuntu 16.04 using Xfce and lightdm-gtk-greeter.

The machine used is a 'Car-PC' with an M2-ATX power supply but should be applicable om most systems where a 'Power button' (or switch), is used for start and stop.

Prerequisites:

Systemd is, since Ubuntu 15.04, the default method starting and stopping system and applications. Systemd simply assumes that all running applications are closed at the instant a 'SIGTERM' is sent to the application causing programs like OpenCPN to, more or less, 'come crashing down'. This is valid for many other programs as well. Have seen 'Chrome, Firefox, OpenOffice and many others do the same. Even e.g Gnome3 has this 'problem' and inspired to the solution used here.

First:

OpenCPN shall be run by a dedicated user (not root!) and should, by systemd, be run as '–user'. This option is badly supported due to the lack of support for graphical shells using targets and services. The method used here will, as there is only one (automatically logged in) user on the system, serve the same purpose.

Enable automatic login:

  [SeatDefaults]
  autologin-user=<user>

Modify systemd settings:

 sudo loginctl enable-linger <user>
 
* Allow user processes to be run after the user has logged out, use 'sudo' and update '/etc/systemd/logind.conf' removing the hashmark for 'KillUserProcesses=no'. Do NOT remove the hashmark for any of the 'Handle' options.

Start script for OpenCPN:

-----------------
#!/bin/bash

STARTCMD="/bin/su <user> -c /usr/bin/opencpn &"
/bin/systemd-inhibit --what=handle-power-key --mode=block ${STARTCMD}

exit 0
-----------------

Enable systemd to start OpenCPN:

-----------------
[Unit]
Description=opencpn
BindsTo=display-manager.service lightdm.service graphical.target
ConditionPathIsReadWrite=/
RequiresMountsFor=/
After=display-manager.service lightdm.service graphical.target
Conflicts=exit.target shutdown.target reboot.target halt.target

[Service]
Type=oneshot
RemainAfterExit=yes
Environment=DISPLAY=:0.0
Environment=Xauthority=/home/<user>/.Xauthority
ExecStart=/usr/local/bin/ocpnStart
ExecStop=/bin/true

[Install]
WantedBy=graphical.target
-----------------

You may also see a number of ALSA messages, these are another story an can be safely ignored.

Shutting down OpenCPN gracefully:

button/power PBTN 00000080 00000000
button/power LNXPWRBN:00 00000080 00000001
button/power PBTN 00000080 00000000
button/power LNXPWRBN:00 00000080 00000002
  -----------------
  #!/bin/bash
  # /etc/acpi/powerbtn.sh
  # Initiates a shutdown when power button has been pressed

  USER=<user>

  if /usr/bin/pgrep -u $USER opencpn > /dev/null ; then
  /usr/bin/pkill -u $USER opencpn
  fi

  /bin/sleep 1
  /sbin/shutdown -h now
  -----------------

A bonus addition: Shutting down thru Xfce:

  -----------------
  #!/bin/bash
  
  wmctrl -c opencpn
  sleep 1
  /usr/bin/xfce4-session-logout -h
  
  exit 0
  -----------------

For slow OpenCPN Shut down

After updating to 5.0 I found an potential problem as 5.0 seems much slower in shutting down, it even, when using S57 charts, throws up the Wait/Terminate message before shutting down.

To cope with that I've added a 'process running check' to the shutdown scripts in the 'Graceful shutdown procedure' published in the wiki. The scripts shall now read:

'/etc/acpi/powerbtn.sh':

-----------------------------------

#!/bin/bash
# /etc/acpi/powerbtn.sh
# Initiates a shutdown when power button has been
# pressed

USER=<user>

if /usr/bin/pgrep -u $USER opencpn > /dev/null ; then
  /usr/bin/pkill -u $USER opencpn
fi
while (pgrep -x opencpn >/dev/null); do
  sleep 1
done
sleep 2
/sbin/shutdown -h now

-----------------------------------

'/usr/local/bin/xfce4-session-logout'

-----------------------------------------

#!/bin/bash

wmctrl -c opencpn
while (pgrep -x opencpn >/dev/null); do
  sleep 1
done
sleep 2
/usr/bin/xfce4-session-logout -h

exit 0

----------------------------------------

That should be all. Enjoy! Hope this explains my view on what is happening and can be of use to you

Best Regards [LennartG] Lennart Gilander

Addendum

MaVi writes:

Well, first I misread what the line

<Code> sudo sed -e '/shutdown/ s/^#*/#/' -i /etc/rc.local </code>

actually does, which explained why I could not find the trigger for the script. It is triggered at boot time.. So I created a simple script from the graceful shutdown page , basically:

#!/bin/bash
# /etc/acpi/powerbtn.sh
# Initiates a shutdown when power button has been
# pressed
LOGFILE=/home/pi/shutdownlog.log
$USER=pi

echo '$(date) OCPN stop request received' >> $LOGFILE
if /usr/bin/pgrep -u $USER opencpn > /dev/null ; then
  echo '$(date) OCPN found running. Stopping now' >> $LOGFILE
  /usr/bin/pkill -u $USER opencpn
fi
while (pgrep -x opencpn >/dev/null); do
  sleep 1
  echo '$(date) Waiting for OCPN to stop' >> $LOGFILE
done
echo '$(date) OCPN stopped' >> $LOGFILE
sleep 2

as killOCPN.sh (and of course chmod +x'ed) Next I added the killOPCN command into the /etc/x710pwr.sh script , just before the 'sudo poweroff' and 'sudo reboot' lines.

The one thing I haven't figured out yet is how to use a simple shutdown button press insted of the long press that is now required- I can shorten the rebootpulsemaximum, but then the X710 does not power-off, but that's for the next rainy sunday afternoon…